Purpose:

The datetime module includes functions and classes for doing date and time parsing, formatting, and arithmetic.

Times

Time value are represented with the time class. A time has attributes for hour, minute, second and microsecond and can also include time zone information.


In [1]:
import datetime

t = datetime.time(1, 2, 3)

print(t)
print('hour       :', t.hour)
print('minute     :', t.minute)
print('second     :', t.second)
print('microsecond:', t.microsecond)
print('tzinfo     :', t.tzinfo)


01:02:03
hour       : 1
minute     : 2
second     : 3
microsecond: 0
tzinfo     : None

datetime min max


In [2]:
import datetime

print('Earliest    :', datetime.time.min)
print("Latest      :", datetime.time.max)
print("Resolution  :", datetime.time.resolution)


Earliest    : 00:00:00
Latest      : 23:59:59.999999
Resolution  : 0:00:00.000001

Note:

the resolution for time is limited to whole microseconds


In [3]:
import datetime

for m in [1, 0, 0.1, 0.6]:
    try:
        print('{:02.1f} :'.format(m),
              datetime.time(0, 0, 0, microsecond=m))
    except TypeError as err:
        print('ERROR:', err)


1.0 : 00:00:00.000001
0.0 : 00:00:00
ERROR: integer argument expected, got float
ERROR: integer argument expected, got float

Dates

Calendar date values are represented with the date class. Instances have attributes for year, month, and day. It is easy to create a date representing the current date using the today() class method.


In [4]:
import datetime

today = datetime.date.today()

print(today)
print("ctime  :", today.ctime())
tt = today.timetuple()

print('tuple  : tm_year  =', tt.tm_year)
print('         tm_mon   =', tt.tm_mon)
print('         tm_mday  =', tt.tm_mday)
print('         tm_hour  =', tt.tm_hour)
print('         tm_min   =', tt.tm_min)
print('         tm_sec   =', tt.tm_sec)
print('         tm_wday  =', tt.tm_wday)
print('         tm_yday  =', tt.tm_yday)
print('         tm_isdst =', tt.tm_isdst)
print('ordinal:', today.toordinal())
print('Year   :', today.year)
print('Mon    :', today.month)
print('Day    :', today.day)


2017-11-10
ctime  : Fri Nov 10 00:00:00 2017
tuple  : tm_year  = 2017
         tm_mon   = 11
         tm_mday  = 10
         tm_hour  = 0
         tm_min   = 0
         tm_sec   = 0
         tm_wday  = 4
         tm_yday  = 314
         tm_isdst = -1
ordinal: 736643
Year   : 2017
Mon    : 11
Day    : 10

There are also class methods for creating instances from POSIX timestamps or integers representing date values from the Gregorian calendar, where January 1 of the year 1 is 1 and each subsequent day increments the value by 1.


In [5]:
import datetime
import time

o = 733114
print('o               :', o)
print('fromordinal(o)  :', datetime.date.fromordinal(o))

t = time.time()
print('t               :', t)
print('fromtimestamp(t):', datetime.date.fromtimestamp(t))


o               : 733114
fromordinal(o)  : 2008-03-13
t               : 1510296445.1038256
fromtimestamp(t): 2017-11-10

As with time, the range of date values supported can be determined using the min and max attributes.


In [6]:
import datetime

print('Earliest  :', datetime.date.min)
print('Latest    :', datetime.date.max)
print('Resolution:', datetime.date.resolution)


Earliest  : 0001-01-01
Latest    : 9999-12-31
Resolution: 1 day, 0:00:00

Another way to create new date instances uses the replace() method of an existing date.


In [7]:
import datetime

d1 = datetime.date(2008, 3, 29)
print('d1:', d1.ctime())

d2 = d1.replace(year=2009)
print('d2:', d2.ctime())


d1: Sat Mar 29 00:00:00 2008
d2: Sun Mar 29 00:00:00 2009

timedeltas

Future and past dates can be calculated using basic arithmetic on two datetime objects, or by combining a datetime with a timedelta. Subtracting dates produces a timedelta, and a timedelta can be added or subtracted from a date to produce another date. The internal values for a timedelta are stored in days, seconds, and microseconds.


In [8]:
import datetime

print('microseconds:', datetime.timedelta(microseconds=1))
print('milliseconds:', datetime.timedelta(milliseconds=1))
print('seconds     :', datetime.timedelta(seconds=1))
print('minutes     :', datetime.timedelta(minutes=1))
print('hours       :', datetime.timedelta(hours=1))
print('days        :', datetime.timedelta(days=1))
print('weeks       :', datetime.timedelta(weeks=1))


microseconds: 0:00:00.000001
milliseconds: 0:00:00.001000
seconds     : 0:00:01
minutes     : 0:01:00
hours       : 1:00:00
days        : 1 day, 0:00:00
weeks       : 7 days, 0:00:00

The full duration of a timedelta can be retrieved as a number of seconds using total_seconds().


In [9]:
import datetime

for delta in [datetime.timedelta(microseconds=1),
              datetime.timedelta(milliseconds=1),
              datetime.timedelta(seconds=1),
              datetime.timedelta(minutes=1),
              datetime.timedelta(hours=1),
              datetime.timedelta(days=1),
              datetime.timedelta(weeks=1),
              ]:
    print('{:15} = {:8} seconds'.format(
        str(delta), delta.total_seconds())
    )


0:00:00.000001  =    1e-06 seconds
0:00:00.001000  =    0.001 seconds
0:00:01         =      1.0 seconds
0:01:00         =     60.0 seconds
1:00:00         =   3600.0 seconds
1 day, 0:00:00  =  86400.0 seconds
7 days, 0:00:00 = 604800.0 seconds

Date Arithmetic

Date math uses the standard arithmetic operators.


In [10]:
import datetime

today = datetime.date.today()
print('Today    :', today)

one_day = datetime.timedelta(days=1)
print('One day  :', one_day)

yesterday = today - one_day
print('Yesterday:', yesterday)

tomorrow = today + one_day
print('Tomorrow :', tomorrow)

print()
print('tomorrow - yesterday:', tomorrow - yesterday)
print('yesterday - tomorrow:', yesterday - tomorrow)


Today    : 2017-11-10
One day  : 1 day, 0:00:00
Yesterday: 2017-11-09
Tomorrow : 2017-11-11

tomorrow - yesterday: 2 days, 0:00:00
yesterday - tomorrow: -2 days, 0:00:00

A timedelta object also supports arithmetic with integers, floats, and other timedelta instances.


In [11]:
import datetime

one_day = datetime.timedelta(days=1)
print('1 day    :', one_day)
print('5 days   :', one_day * 5)
print('1.5 days :', one_day * 1.5)
print('1/4 day  :', one_day / 4)

# assume an hour for lunch
work_day = datetime.timedelta(hours=7)
meeting_length = datetime.timedelta(hours=1)
print('meetings per day :', work_day / meeting_length)


1 day    : 1 day, 0:00:00
5 days   : 5 days, 0:00:00
1.5 days : 1 day, 12:00:00
1/4 day  : 6:00:00
meetings per day : 7.0

Comparing Values

Both date and time values can be compared using the standard comparison operators to determine which is earlier or later.


In [13]:
import datetime
import time

print('Times:')
t1 = datetime.time(12, 55, 0)
print('  t1:', t1)
t2 = datetime.time(13, 5, 0)
print('  t2:', t2)
print('  t1 < t2:', t1 < t2)

print()
print('Dates:')
d1 = datetime.date.today()
print('  d1:', d1)
d2 = datetime.date.today() + datetime.timedelta(days=1)
print('  d2:', d2)
print('  d1 > d2:', d1 > d2)


Times:
  t1: 12:55:00
  t2: 13:05:00
  t1 < t2: True

Dates:
  d1: 2017-11-10
  d2: 2017-11-11
  d1 > d2: False

Combining Dates and Times

Use the datetime class to hold values consisting of both date and time components. As with date, there are several convenient class methods to make creating datetime instances from other common values.


In [14]:
import datetime

print('Now    :', datetime.datetime.now())
print('Today  :', datetime.datetime.today())
print('UTC Now:', datetime.datetime.utcnow())
print()

FIELDS = [
    'year', 'month', 'day',
    'hour', 'minute', 'second',
    'microsecond',
]

d = datetime.datetime.now()
for attr in FIELDS:
    print('{:15}: {}'.format(attr, getattr(d, attr)))


Now    : 2017-11-10 15:05:31.754458
Today  : 2017-11-10 15:05:31.754801
UTC Now: 2017-11-10 07:05:31.754880

year           : 2017
month          : 11
day            : 10
hour           : 15
minute         : 5
second         : 31
microsecond    : 755005

combine date and time


In [15]:
import datetime

t = datetime.time(1, 2, 3)
print('t :', t)

d = datetime.date.today()
print('d :', d)

dt = datetime.datetime.combine(d, t)
print('dt:', dt)


t : 01:02:03
d : 2017-11-10
dt: 2017-11-10 01:02:03

Formatting and Parsing

The default string representation of a datetime object uses the ISO-8601 format (YYYY-MM-DDTHH:MM:SS.mmmmmm). Alternate formats can be generated using strftime().


In [16]:
import datetime

format = "%a %b %d %H:%M:%S %Y"

today = datetime.datetime.today()
print('ISO     :', today)

s = today.strftime(format)
print('strftime:', s)

d = datetime.datetime.strptime(s, format)
print('strptime:', d.strftime(format))


ISO     : 2017-11-10 15:09:12.672865
strftime: Fri Nov 10 15:09:12 2017
strptime: Fri Nov 10 15:09:12 2017

Time Zones

Within datetime, time zones are represented by subclasses of tzinfo. Since tzinfo is an abstract base class, applications need to define a subclass and provide appropriate implementations for a few methods to make it useful.

datetime does include a somewhat naive implementation in the class timezone that uses a fixed offset from UTC, and does not support different offset values on different days of the year, such as where daylight savings time applies, or where the offset from UTC has changed over time


In [20]:
import datetime

min6 = datetime.timezone(datetime.timedelta(hours=-6))
plus6 = datetime.timezone(datetime.timedelta(hours=6))

print("now:", datetime.datetime.now())

d = datetime.datetime.now(min6)

print(min6, ':', d)
print(datetime.timezone.utc, ':',
      d.astimezone(datetime.timezone.utc))
print(plus6, ':', d.astimezone(plus6))

# convert to the current system timezone
d_system = d.astimezone()
print(d_system.tzinfo, '      :', d_system)


now: 2017-11-10 15:14:54.960605
UTC-06:00 : 2017-11-10 01:14:54.960954-06:00
UTC : 2017-11-10 07:14:54.960954+00:00
UTC+06:00 : 2017-11-10 13:14:54.960954+06:00
CST       : 2017-11-10 15:14:54.960954+08:00

The third party module pytz is a better implementation for time zones. It supports named time zones, and the offset database is kept up to date as changes are made by political bodies around the world.


In [ ]: